// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// e32\euser\maths\um_pow10.cpp
// Return a power of 10 as a TReal
// 
//

#include "um_std.h"

#if defined(__USE_VFP_MATH) && !defined(__CPU_HAS_VFP)
#error	__USE_VFP_MATH was defined but not __CPU_HAS_VFP - impossible combination, check variant.mmh 
#endif


// Tables of powers of 10
LOCAL_D const TUint32 PositivePowersOfTen[] =
	{
// Positive powers 1-31
	0x00000000,0xA0000000,0x80020000,
	0x00000000,0xC8000000,0x80050000,
	0x00000000,0xFA000000,0x80080000,
	0x00000000,0x9C400000,0x800C0000,
	0x00000000,0xC3500000,0x800F0000,
	0x00000000,0xF4240000,0x80120000,
	0x00000000,0x98968000,0x80160000,
	0x00000000,0xBEBC2000,0x80190000,
	0x00000000,0xEE6B2800,0x801C0000,
	0x00000000,0x9502F900,0x80200000,
	0x00000000,0xBA43B740,0x80230000,
	0x00000000,0xE8D4A510,0x80260000,
	0x00000000,0x9184E72A,0x802A0000,
	0x80000000,0xB5E620F4,0x802D0000,
	0xA0000000,0xE35FA931,0x80300000,
	0x04000000,0x8E1BC9BF,0x80340000,
	0xC5000000,0xB1A2BC2E,0x80370000,
	0x76400000,0xDE0B6B3A,0x803A0000,
	0x89E80000,0x8AC72304,0x803E0000,
	0xAC620000,0xAD78EBC5,0x80410000,
	0x177A8000,0xD8D726B7,0x80440000,
	0x6EAC9000,0x87867832,0x80480000,
	0x0A57B400,0xA968163F,0x804B0000,
	0xCCEDA100,0xD3C21BCE,0x804E0000,
	0x401484A0,0x84595161,0x80520000,
	0x9019A5C8,0xA56FA5B9,0x80550000,
	0xF4200F3A,0xCECB8F27,0x80580000,
	0xF8940984,0x813F3978,0x805C0000,
	0x36B90BE5,0xA18F07D7,0x805F0000,
	0x04674EDF,0xC9F2C9CD,0x80620000,
	0x45812296,0xFC6F7C40,0x80650000,

// Positive powers 32-31*32 in steps of 32
	0x2B70B59E,0x9DC5ADA8,0x80690000,
	0xFFCFA6D5,0xC2781F49,0x80D30000,
	0xC59B14A3,0xEFB3AB16,0x813D0000,
	0x80E98CE0,0x93BA47C9,0x81A80000,
	0x7FE617AA,0xB616A12B,0x82120000,
	0x3927556B,0xE070F78D,0x827C0000,
	0xE33CC930,0x8A5296FF,0x82E70000,
	0x9DF9DE8E,0xAA7EEBFB,0x83510000,
	0x5C6A2F8C,0xD226FC19,0x83BB0000,
	0xF2CCE376,0x81842F29,0x84260000,
	0xDB900AD2,0x9FA42700,0x84900000,
	0xAEF8AA17,0xC4C5E310,0x84FA0000,
	0xE9B09C59,0xF28A9C07,0x85640000,
	0xEBF7F3D4,0x957A4AE1,0x85CF0000,
	0x0795A262,0xB83ED8DC,0x86390000,
	0xA60E91C7,0xE319A0AE,0x86A30000,
	0x432D7BC3,0x8BF61451,0x870E0000,
	0x6B6795FD,0xAC83FB89,0x87780000,
	0xB8FA79B0,0xD4A44FB4,0x87E20000,
	0xE54A9D1D,0x830CF791,0x884D0000,
	0xADE24964,0xA1884B69,0x88B70000,
	0x1F8F01CC,0xC71AA36A,0x89210000,
	0x437028F3,0xF56A298F,0x898B0000,
	0xCD00A68C,0x973F9CA8,0x89F60000,
	0xD7CC9ECD,0xBA6D9B40,0x8A600000,
	0x8D737F0E,0xE5CA5A0B,0x8ACA0000,
	0x1346BDA5,0x8D9E89D1,0x8B350000,
	0xE3D5DBEA,0xAE8F2B2C,0x8B9F0000,
	0x5A0C1B30,0xD7293020,0x8C090000,
	0x0D2ECFD2,0x849A672A,0x8C740000,
	0x41FA93DE,0xA3722C13,0x8CDE0000,

// Positive powers 1024-8*1024 in steps of 1024
	0x81750C17,0xC9767586,0x8D480000,
	0xC53D5DE5,0x9E8B3B5D,0x9A920000,
	0xD88B5A8B,0xF9895D25,0xA7DB0000,
	0x8A20979B,0xC4605202,0xB5250000,
	0xFED3AB23,0x9A8A7EF0,0xC26F0000,
	0x73A56037,0xF33C80E8,0xCFB80000,
	0x61889066,0xBF6B0EC4,0xDD020000,
	0x7FAF211A,0x96A3A1D1,0xEA4C0000
	};

LOCAL_D const TUint32 NegativePowersOfTen[] =
	{
// Negative powers 1-31
	0xCCCCCCCD,0xCCCCCCCC,0x7FFB0000,
	0x70A3D70A,0xA3D70A3D,0x7FF80000,
	0x8D4FDF3B,0x83126E97,0x7FF50000,
	0xE219652C,0xD1B71758,0x7FF10000,
	0x1B478423,0xA7C5AC47,0x7FEE0000,
	0xAF6C69B6,0x8637BD05,0x7FEB0000,
	0xE57A42BC,0xD6BF94D5,0x7FE70000,
	0x8461CEFD,0xABCC7711,0x7FE40000,
	0x36B4A597,0x89705F41,0x7FE10000,
	0xBDEDD5BF,0xDBE6FECE,0x7FDD0000,
	0xCB24AAFF,0xAFEBFF0B,0x7FDA0000,
	0x6F5088CC,0x8CBCCC09,0x7FD70000,
	0x4BB40E13,0xE12E1342,0x7FD30000,
	0x095CD80F,0xB424DC35,0x7FD00000,
	0x3AB0ACD9,0x901D7CF7,0x7FCD0000,
	0xC44DE15B,0xE69594BE,0x7FC90000,
	0x36A4B449,0xB877AA32,0x7FC60000,
	0x921D5D07,0x9392EE8E,0x7FC30000,
	0xB69561A5,0xEC1E4A7D,0x7FBF0000,
	0x92111AEB,0xBCE50864,0x7FBC0000,
	0x74DA7BEF,0x971DA050,0x7FB90000,
	0xBAF72CB1,0xF1C90080,0x7FB50000,
	0x95928A27,0xC16D9A00,0x7FB20000,
	0x44753B53,0x9ABE14CD,0x7FAF0000,
	0xD3EEC551,0xF79687AE,0x7FAB0000,
	0x76589DDB,0xC6120625,0x7FA80000,
	0x91E07E48,0x9E74D1B7,0x7FA50000,
	0x8300CA0E,0xFD87B5F2,0x7FA10000,
	0x359A3B3E,0xCAD2F7F5,0x7F9E0000,
	0x5E14FC32,0xA2425FF7,0x7F9B0000,
	0x4B43FCF5,0x81CEB32C,0x7F980000,

// Negative powers 32-31*32 in steps of 32
	0x453994BA,0xCFB11EAD,0x7F940000,
	0xA539E9A5,0xA87FEA27,0x7F2A0000,
	0xFD75539B,0x88B402F7,0x7EC00000,
	0x64BCE4A1,0xDDD0467C,0x7E550000,
	0xDB73A093,0xB3F4E093,0x7DEB0000,
	0x5423CC06,0x91FF8377,0x7D810000,
	0x4A314EBE,0xECE53CEC,0x7D160000,
	0x637A193A,0xC0314325,0x7CAC0000,
	0x836AC577,0x9BECCE62,0x7C420000,
	0x478238D1,0xFD00B897,0x7BD70000,
	0x46F34F7D,0xCD42A113,0x7B6D0000,
	0xB11B0858,0xA686E3E8,0x7B030000,
	0x3FFC68A6,0x871A4981,0x7A990000,
	0xB6074245,0xDB377599,0x7A2E0000,
	0x79007736,0xB1D983B4,0x79C40000,
	0xDB23D21C,0x9049EE32,0x795A0000,
	0x467F9466,0xEA1F3806,0x78EF0000,
	0xEE5092C7,0xBDF139F0,0x78850000,
	0xB4730DD0,0x9A197865,0x781B0000,
	0x8871347D,0xFA0A6CDB,0x77B00000,
	0x3C8736FC,0xCADB6D31,0x77460000,
	0x52EB8375,0xA493C750,0x76DC0000,
	0x774FB85E,0x85855C0F,0x76720000,
	0x505DE96B,0xD8A66D4A,0x76070000,
	0xCB39A7B1,0xAFC47766,0x759D0000,
	0xA9B05AC8,0x8E997872,0x75330000,
	0xFDC06462,0xE761832E,0x74C80000,
	0xBB827F2D,0xBBB7EF38,0x745E0000,
	0xE1F045DD,0x984B9B19,0x73F40000,
	0x3613F568,0xF71D01E0,0x73890000,
	0x3F64789E,0xC87B6D2F,0x731F0000,

// Negative powers 1024-8*1024 in steps of 1024
	0xDA57C0BE,0xA2A682A5,0x72B50000,
	0x34362DE4,0xCEAE534F,0x656B0000,
	0x91575A88,0x8350BF3C,0x58220000,
	0xD2CE9FDE,0xA6DD04C8,0x4AD80000,
	0x0DA5D8E8,0xD408CB01,0x3D8E0000,
	0x22EB58E9,0x86B77A60,0x30450000,
	0x4779611E,0xAB2F7655,0x22FB0000,
	0x686DA869,0xD986C20B,0x15B10000
	};

TInt Math::MultPow10X(TRealX& aTrg, TInt aPower)
	{
	if (aTrg.IsZero())
		return KErrNone;
	if (!aTrg.IsFinite())
		{
		if (aTrg.IsNaN())
			return KErrArgument;
		return KErrOverflow;
		}
	if (aPower==0)
		return KErrNone;
	// smallest non-zero TRealX is 2^-32766=2.83E-9864
	// largest TRealX is 2^32768=1.42E+9864
	// Therefore aPower>=19728 guarantees an overflow
	// and aPower<=-19728 guarantees an underflow
	if (aPower>=19728)
		{
		aTrg.SetInfinite(aTrg.iSign);
		return KErrOverflow;
		}
	if (aPower<=-19728)
		{
		aTrg.SetZero(aTrg.iSign);
		return KErrUnderflow;
		}
	const TRealX* powTab;
	if (aPower>0)
		powTab=(const TRealX*)PositivePowersOfTen;
	else
		{
		aPower=-aPower;
		powTab=(const TRealX*)NegativePowersOfTen;
		}
	TInt r=KErrNone;
	while(aPower>=8192)
		{
		aPower-=8192;
		r=aTrg.MultEq(powTab[31+31+7]);
		if (r!=KErrNone)
			return r;
		}
	TInt bottom5=aPower & 0x1f;
	TInt middle5=(aPower>>5)&0x1f;
	TInt top3=(aPower>>10);
	if (top3)
		r=aTrg.MultEq(powTab[31+31+top3-1]);
	if (r==KErrNone && middle5)
		r=aTrg.MultEq(powTab[31+middle5-1]);
	if (r==KErrNone && bottom5)
		r=aTrg.MultEq(powTab[bottom5-1]);
	return r;
	}




EXPORT_C TInt Math::Pow10(TReal &aTrg,const TInt aExp)
/**
Calculates the value of 10 to the power of x.

@param aTrg A reference containing the result. 
@param aExp The power to which 10 is to be raised.

@return KErrNone if successful, otherwise another of
        the system-wide error codes.
*/
//
// Write the binary floating point representation of a power of 10 to aSrc
// Returns KErrNone if OK or a negative error number otherwise.
//
	{
#ifndef __USE_VFP_MATH
	TRealX x=1;
	TInt r=Math::MultPow10X(x,aExp);
	TInt s=x.GetTReal(aTrg);
	return (r==KErrNone)?s:r;
#else // __USE_VFP_MATH
	return Math::Pow(aTrg,10,aExp);
#endif
	}
